#ifndef DIST_H
#define DIST_H

#include "common.h"
#include "vector.h"
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef double (*f_dbl)();

// activity_summary的别名，区别在于使用链表
typedef struct _staging_data {
  uint64_t start_time;
  uint64_t end_time;
  double avg_hr;
  linked_list_t *slist;
} alias_acts_ll_t;

typedef struct _seg_info {
  size_t start_index;
  size_t end_index;
  double hr_avg;
  double hr_sd;
  double hrv_avg;
  double hrv_sd;
  double motion_avg;
  double motion_sd;
  double steps_sd;
  int32_t steps_diff;
  /*
  该字段表示因为原始数据节点序号相同时
  造成不计算而失效
   */
  uint32_t valid;
} seg_info_t;

typedef struct _sleep_start_end {
  size_t start_index;
  size_t end_index;
} sleep_start_end_t;

#define _CSEM_M(f) f##_M

typedef struct _csem_ext {
  uint64_t _CSEM_M(STAGING_LIGHT_SLEEP_TIME);
  uint64_t _CSEM_M(SLEEP_RANGE_MERGE_TIME);
  uint64_t _CSEM_M(SLEEP_FRAGMENT_MIN_NAP_TIME);
  uint64_t _CSEM_M(WAKE2SLEEP_INTERVAL_TIME);
  uint64_t _CSEM_M(MINIMUM_SLEEP_TIME);
  uint64_t _CSEM_M(N3_MOTION_THRESHOLD);
  f_dbl _CSEM_M(N1_MOTION_THRESHOLD);
  uint64_t _CSEM_M(MIN_STAGING_TIME);
} csem_ext_t;

#define DEF_EVAL(dist, f) (dist->csem_ext ? dist->csem_ext->f##_M : f)

typedef struct _dist_act {
  csem_ext_t *csem_ext;
  /*
  对测量数据预处理
  如多PD数据重叠时
  具体见ListUtils.kt:processList
   */
  smp_hr_t *(*pre_proc)(const smp_hr_t *src_list, size_t count,
                        size_t *dst_count);
  /*
  销毁对process函数生成的数据
  对于v3,仅转换类型，因此空调用即可
   */
  void (*pre_release)(smp_hr_t *processed_list);
  /*
  仅v4考虑wake选项
   */
  uint8_t (*count4wake)(void);
  /*
  _proc函数的条件判断
  v4中判断时间是否一致
   */
  uint8_t (*proc_cond)(const alias_acts_ll_t *, uint64_t);
  uint8_t (*sleep_range_cond)(const seg_info_t *);
  uint8_t (*find_sleep_start_end_impl)(uint8_t strict_mode,
                                       const smp_hr_t *hr_data, size_t len,
                                       size_t index_start, size_t index_end,
                                       size_t *out_start, size_t *out_end);
  uint8_t (*sleep_staging_min_cond)(const struct _dist_act *dist,
                                    uint64_t sleep_start, const smp_hr_t *slist,
                                    size_t count);
  uint8_t (*staging_type_cond)(uint32_t last_hr);
  void (*segment_calc)(const smp_hr_t *hr_list, size_t count,
                       uint32_t time_minute, seg_info_t *result_list,
                       size_t *len_result);
  /*
  判定是否已佩戴
   */
  uint8_t (*is_wear)(const smp_hr_t *hr_list, const uint32_t *slist,
                     size_t count);
  // acc工作正常
  uint8_t (*is_acc_func)(const smp_hr_t *list, size_t count);
} dist_action_t;

// 定义在不同版本的实现文件中
extern dist_action_t ver_sel;
extern csem_ext_t csem_ei;

#ifdef __cplusplus
}
#endif

#endif